#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>

/* Numero de Threads */
#define NUM_THREADS 4

pthread_t thread[NUM_THREADS];

/* Mutex, impede que duas Threads acessem ao mesmo tempo a soma */
pthread_mutex_t mutexsum;

/* Numero de iteracoes (10^9) */
#define n_iter 1000000000

double soma;

/* Funcao que calcula parte do PI */
void *Calculo(void *id){
  
  int sum, i;
  double x, y, z;
  short unsigned int vector[3];

  sum=0;

  for(i=0;i<(n_iter/NUM_THREADS);i++){
    
    /* x e y sempre sao menores do que UM */
    x = erand48(vector);
    y = erand48(vector);

    z = x*x+y*y;

    if (z<=1)
      sum++;

  }

  /* Trava o mutex para acessar a variavel global */
  pthread_mutex_lock (&mutexsum);
  soma += sum;
  /* Destrava */
  pthread_mutex_unlock (&mutexsum);

  pthread_exit((void*) id);

}


int main(){

  srand(time(NULL));
    int rc;
    long t;
    void *status;
    double pi=0;
    soma=0;
    /* Inicializa todas as Threads */
    for(t=0; t<NUM_THREADS; t++) {        
        
        rc = pthread_create(&thread[t], NULL, Calculo, (void *)t); 
        if (rc) {
          printf("ERRO; codigo de retorno da pthread_create(): %d\n", rc);
          exit(-1);
        }
    }

   /* Espera as Threads acabarem */
   for(t=0; t<NUM_THREADS; t++) {
        rc = pthread_join(thread[t], &status);
        if (rc) {
          printf("ERRO; codigo de retorno da pthread_join() : %d\n", rc);
          exit(-1);
        }       
    } 

    pi=((double)soma/n_iter) * 4;
    printf("%.6f\n", pi);
  
  pthread_exit(NULL);

  
  return 0;
}